package com.codeanalysissys.backend.controller;

import com.codeanalysissys.backend.entity.Analysis;
import com.codeanalysissys.backend.entity.Language;
import com.codeanalysissys.backend.entity.response.ResponseCode;
import com.codeanalysissys.backend.entity.response.Result;
import com.codeanalysissys.backend.service.core.CodeAnalysisService;
import com.codeanalysissys.backend.utils.CookieUtil;
import com.codeanalysissys.backend.utils.RedisCache;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/edits")
public class EditController {
    @Autowired
    private CodeAnalysisService codeAnalysisService;
    @Autowired
    private CookieUtil cookieUtil;
    @Autowired
    private RedisCache redisCache;

    /**
     * 提交源代码，进行分析
     *
     * @param lang
     * @param content
     * @param type
     * @return
     */
    @PostMapping("/submit")
    public Result submitSourceCode(@RequestParam("lang") Language lang, @RequestParam("content") String content, @RequestParam("type") Analysis type) {
//        return codeAnalysisServiceFactory.getService(lang.getName()).analysis(content, type);
        return codeAnalysisService.analysis(content, type, lang);
    }

    /**
     * 提交源代码，进行分析
     *
     * @param lang
     * @param content
     * @return
     */
    @PostMapping("/submit-for-all")
    public Result submitSourceCode(@RequestParam("lang") Language lang, @RequestParam("content") String content) {
//        return codeAnalysisServiceFactory.getService(lang.getName()).analysisAll(content);
        return codeAnalysisService.analysisAll(content, lang);
    }

    /**
     * 保存当前源代码，若当前浏览器没携带cookie就生成新的
     *
     * @param content  源代码
     * @param key      cookie名：edit
     * @param request  请求
     * @param response 响应
     * @return 源代码保存成功信息
     */
    @PostMapping("/save")
    public ResponseEntity<String> saveCode(@RequestParam("content") String content,
                                           @RequestParam("lang") String lang,
                                           @RequestParam("key") String key,
                                           HttpServletRequest request, HttpServletResponse response) {
        // 获取携带的 cookie，cookie 名为 "edit"
        Cookie currentCookie = cookieUtil.getUserCookie(request, key);

        if (currentCookie != null) {
            // 若携带着 cookie，意味着 redis 中有缓存源代码，直接更新该 cookie 对应的源代码并更新有效期
            HashMap<String, String> data = new HashMap<>();
            data.put("content", content);
            data.put("lang", lang);
            redisCache.setCacheObject(currentCookie.getValue(), data, 1, TimeUnit.DAYS);

            // 一同更新 cookie 的有效期
            currentCookie.setMaxAge(86400);
            response.addCookie(currentCookie);
        } else {
            // 若没携带 cookie，则生成 cookie 并设置有效期为一天
            String newCookieValue = cookieUtil.generateUUID();
            Cookie newCookie = new Cookie(key, newCookieValue);
            newCookie.setMaxAge(86400);
            response.addCookie(newCookie);
            // 将该 cookieValue 和 content 存入 redis，设置有效期为一天
            redisCache.setCacheObject(newCookieValue, content, 1, TimeUnit.DAYS);
        }

        return ResponseEntity.ok("Code saved successfully.");
    }

    @GetMapping("/recover")
    public Result recoverCode(String key, HttpServletRequest request) {
        // 获取携带的 cookie，cookie 名为 "edit"
        Cookie currentCookie = cookieUtil.getUserCookie(request, key);

        // 若携带着 cookie，从 redis 中读取保存的源代码
        if (currentCookie != null) {
            Map<String, String> data = redisCache.getCacheObject(currentCookie.getValue());
            if (data != null && !data.isEmpty()) {
                return new Result.Builder(ResponseCode.GET_SUCCESS).data(data).build();
            }
        }

        return new Result.Builder(ResponseCode.GET_FAIL).build();
    }

    /**
     * 获取当前源代码
     *
     * @param type
     * @return
     */
    @GetMapping("/get-graph")
    public Analysis typeConvert(@RequestParam("type") Analysis type) {
        return type;
    }

    @GetMapping("/get-lang")
    public Language langConvert(@RequestParam("lang") Language lang) {
        return lang;
    }

}
